home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / progutil / stdwin.zoo / alfa / event.c < prev    next >
C/C++ Source or Header  |  1989-10-18  |  6KB  |  340 lines

  1. /* STDWIN -- EVENTS. */
  2.  
  3. #include "alfa.h"
  4.  
  5. /* There are three levels of event processing.
  6.    The lowest ('raw') level only inputs single characters.
  7.    The middle ('sys') level translates sequences of keys to menu shortcuts
  8.    and 'commands'.
  9.    The highest ('appl') level executes certain commands and can call the
  10.    interactive menu selection code.  It also sets the window parameter.
  11.    For each level there are variants to wait or poll.
  12.    Additional routines to get from one level to another:
  13.    wmapchar: inspect key map and possibly convert char event
  14.    wsyscommand: execute/transform system menu
  15.  
  16. /* Raw event -- read one character.  If blocking is FALSE,
  17.    don't read if trmavail() returns -1, meaning it can't tell whether
  18.    there is input or not.  In that case only synchronous input works. */
  19.  
  20.  
  21. static bool
  22. wrawevent(ep, blocking)
  23.     EVENT *ep;
  24.     bool blocking;
  25. {
  26.     if (!blocking && trmavail() <= 0)
  27.         return FALSE;
  28.     ep->u.character= trminput();
  29.     if (ep->u.character < 0) {
  30.         ep->type= WE_NULL;
  31.         return FALSE;
  32.     }
  33.     else {
  34.         ep->type= WE_CHAR;
  35.         return TRUE;
  36.     }
  37. }
  38.  
  39. static void wmapchar(); /* Forward */
  40.  
  41. /* System event -- read a character and translate using the key map. */
  42.  
  43. bool
  44. wsysevent(ep, blocking)
  45.     EVENT *ep;
  46.     bool blocking;
  47. {
  48.     struct keymap mapentry;
  49.     
  50.     if (!wrawevent(ep, blocking))
  51.         return FALSE;
  52.     /* Using a temporary to avoid a tahoe C compiler bug */
  53.     mapentry= _wprimap[ep->u.character & 0xff];
  54.     wmapchar(ep, mapentry);
  55.     return ep->type != WE_NULL;
  56. }
  57.  
  58. /* Key map translation from raw event.
  59.    This may read more characters if the start of a multi-key sequence is
  60.    found. */
  61.  
  62. static void
  63. wmapchar(ep, mapentry)
  64.     EVENT *ep;
  65.     struct keymap mapentry;
  66. {
  67.     switch (mapentry.type) {
  68.     
  69.     case SHORTCUT:
  70.         ep->type= WE_MENU;
  71.         ep->u.m.id= mapentry.id;
  72.         ep->u.m.item= mapentry.item;
  73.         break;
  74.     
  75.     case SECONDARY:
  76.         if (wrawevent(ep, TRUE)) {
  77.             struct keymap *map;
  78.             struct keymap *altmap= NULL;
  79.             for (map= _wsecmap[mapentry.id];
  80.                 map->type != SENTINEL;
  81.                 ++map) {
  82.                 if (map->key == ep->u.character) {
  83.                     wmapchar(ep, *map);
  84.                     return;
  85.                 }
  86.                 else if (islower(ep->u.character) &&
  87.                     map->key == toupper(ep->u.character))
  88.                     altmap= map;
  89.             }
  90.             if (altmap != NULL) {
  91.                 wmapchar(ep, *altmap);
  92.                 return;
  93.             }
  94.         }
  95.         trmbell();
  96.         ep->type= WE_NULL;
  97.         break;
  98.     
  99.     }
  100. }
  101.  
  102. void
  103. wgoto(ep, type)
  104.     EVENT *ep;
  105.     int type;
  106. {
  107.     int h, v;
  108.     
  109.     trmsense(&v, &h);
  110.     if (v >= 0) {
  111.         WINDOW *win;
  112.         for (win= &winlist[1]; win < &winlist[MAXWINDOWS]; ++win) {
  113.             if (win->open && v >= win->top && v < win->bottom) {
  114.                 if (win == front) {
  115.                     ep->type= type;
  116.                     ep->u.where.h= h;
  117.                     ep->u.where.v= v + win->offset;
  118.                     ep->u.where.clicks= 1;
  119.                     ep->u.where.button= 1;
  120.                     ep->u.where.mask=
  121.                         (type == WE_MOUSE_UP ? 0 : 1);
  122.                     return;
  123.                 }
  124.                 wsetactive(win);
  125.                 break;
  126.             }
  127.         }
  128.     }
  129.     ep->type= WE_NULL;
  130. }
  131.  
  132. void
  133. wmouseup(ep)
  134.     EVENT *ep;
  135. {
  136.     int h, v;
  137.     
  138.     trmsense(&v, &h);
  139.     if (v < 0)
  140.         ep->type= WE_NULL;
  141.     else {
  142.         ep->type= WE_MOUSE_UP;
  143.         ep->u.where.h= h;
  144.         ep->u.where.v= v + front->offset;
  145.         ep->u.where.clicks= 1;
  146.         ep->u.where.button= 1;
  147.         ep->u.where.mask= 0;
  148.     }
  149. }
  150.  
  151. static void wdoupdates(); /* Forward */
  152.  
  153. /* Application event. */
  154.  
  155. static EVENT ebuf;
  156.  
  157. void
  158. wungetevent(ep)
  159.     EVENT *ep;
  160. {
  161.     ebuf= *ep;
  162. }
  163.  
  164. bool
  165. wpollevent(ep)
  166.     EVENT *ep;
  167. {
  168.     return wevent(ep, FALSE);
  169. }
  170.  
  171. void
  172. wgetevent(ep)
  173.     EVENT *ep;
  174. {
  175.     (void) wevent(ep, TRUE);
  176. }
  177.  
  178. static bool
  179. wevent(ep, blocking)
  180.     EVENT *ep;
  181.     bool blocking;
  182. {
  183.     static int lasttype= WE_NULL;
  184.     
  185.     if (ebuf.type != WE_NULL) {
  186.         *ep= ebuf;
  187.         ebuf.type= WE_NULL;
  188.         return TRUE;
  189.     }
  190.     
  191.     ep->type= WE_NULL;
  192.     ep->window= NULL;
  193.     if (lasttype == WE_MOUSE_DOWN)
  194.         wmouseup(ep);
  195.     while (ep->type == WE_NULL) {
  196.         if (front != wasfront) {
  197.             if (wasfront != NULL) {
  198.                 ep->type= WE_DEACTIVATE;
  199.                 ep->window= wasfront;
  200.                 wasfront= NULL;
  201.             }
  202.             else {
  203.                 menubarchanged();
  204.                 ep->type= WE_ACTIVATE;
  205.                 wasfront= front;
  206.             }
  207.         }
  208.         else {
  209.             if (trmavail() <= 0)
  210.                 wdoupdates(ep);
  211.             if (ep->type == WE_NULL) {
  212.                 /* Remove this call if no select() exists */
  213.                 if (_w_checktimer(ep, blocking))
  214.                     break;
  215.                 if (!wsysevent(ep, blocking)) {
  216.                     ep->type= WE_NULL;
  217.                     break;
  218.                 }
  219.                 if (ep->type == WE_MENU && ep->u.m.id == 0)
  220.                     wsyscommand(ep);
  221.             }
  222.         }
  223.     }
  224.     if (ep->window == NULL && front != syswin)
  225.         ep->window= front;
  226.     lasttype= ep->type;
  227.     return ep->type != WE_NULL;
  228. }
  229.  
  230. void
  231. wsyscommand(ep)
  232.     EVENT *ep;
  233. {
  234.     ep->type= WE_NULL;
  235.     
  236.     switch (ep->u.m.item) {
  237.     
  238.     default:
  239.         if (ep->u.m.item <= LAST_CMD) {
  240.             ep->type= WE_COMMAND;
  241.             ep->u.command= ep->u.m.item - FIRST_CMD;
  242.         }
  243.         break;
  244.     
  245.     case NEXT_WIN:
  246.         _wselnext();
  247.         break;
  248.     
  249.     case PREV_WIN:
  250.         _wselprev();
  251.         break;
  252.     
  253.     case SUSPEND_PROC:
  254.         _wsuspend();
  255.         break;
  256.     
  257.     case REDRAW_SCREEN:
  258.         _wredraw();
  259.         break;
  260.     
  261.     case MOUSE_DOWN:
  262.     case MOUSE_UP:
  263.         wgoto(ep, ep->u.m.item - MOUSE_DOWN + WE_MOUSE_DOWN);
  264.         break;
  265.     
  266.     case LITERAL_NEXT:
  267.         _wlitnext(ep);
  268.         break;
  269.     
  270.     case MENU_CALL:
  271.         menuselect(ep);
  272.         break;
  273.     
  274.     }
  275. }
  276.  
  277. /* Flush output and place cursor. */
  278.  
  279. void
  280. wflush()
  281. {
  282.     int y= front->curv - front->offset;
  283.     int x= front->curh;
  284.     
  285.     if (front->curv < 0 || y < front->top || y >= front->bottom) {
  286.         y= front->top;
  287.         if (y > 0)
  288.             --y;
  289.         x= 0;
  290.     }
  291.     else if (x < 0)
  292.         x= 0;
  293.     else if (x >= columns)
  294.         x= columns-1;
  295.     trmsync(y, x);
  296. }
  297.  
  298. /* Process pending window updates.
  299.    If a window has no draw procedure, a WE_DRAW event is generated instead. */
  300.  
  301. static void
  302. wdoupdates(ep)
  303.     EVENT *ep;
  304. {
  305.     WINDOW *win;
  306.     int left, top, right, bottom;
  307.     
  308.     for (win= winlist; win < &winlist[MAXWINDOWS]; ++win) {
  309.         if (win->open) {
  310.             if (win->top > 0 && !uptodate[win->top - 1])
  311.                 wdrawtitle(win);
  312.             if (wgetchange(win, &left, &top, &right, &bottom)) {
  313.                 if (win->drawproc == NULL) {
  314.                     ep->type= WE_DRAW;
  315.                     ep->window= win;
  316.                     ep->u.area.left= left;
  317.                     ep->u.area.top= top;
  318.                     ep->u.area.right= right;
  319.                     ep->u.area.bottom= bottom;
  320.                     return;
  321.                 }
  322.                 else {
  323.                     wbegindrawing(win);
  324.                     (*win->drawproc)(win,
  325.                         left, top, right, bottom);
  326.                     wenddrawing(win);
  327.                 }
  328.             }
  329.         }
  330.     }
  331.     wflush();
  332. }
  333.  
  334. void
  335. _wlitnext(ep)
  336.     EVENT *ep;
  337. {
  338.     (void) wrawevent(ep, TRUE);
  339. }
  340.